package ws.performancetest.app.gui;

import java.awt.Desktop;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.IOException;
import java.sql.SQLException;
import java.util.LinkedList;
import java.util.List;
import java.util.ServiceLoader;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.UIManager;
import ws.performancetest.api.TestSuite;
import ws.utils.jdbc.DBConnection;
import ws.performancetest.app.gui.dialog.ErrorDialog;
import ws.performancetest.app.gui.panel.RunTestJPanel;
import ws.performancetest.app.gui.strings.AppStrings;

/**
 * This is the graphical interface for the main application.
 * 
 * @author Wilson Santos, 36228 <wilson.santos@ua.pt>
 */
public class Application extends javax.swing.JFrame {

  private static final Application reference = new Application();
  /** List of temporary files created. */
  private final List<File> tempFileList = new LinkedList<File>();
  /** After this amount of time (in milliseconds) reset the status label. */
  private final int cleanStatusTimeOut = 10000;
  /** Run tests tab. */
  private static RunTestJPanel tabRunTest;
  /** List with the test suites on classpath. */
  private static List<TestSuite> testSuiteList = null;
  protected static String server;
  protected static String port;
  protected static String username;
  protected static String password;
  /** Name of the database being used. */
  private static String database;

  /** Creates new form NewApplication */
  private Application() {
    /* Set look-and-feel to system. */
    try {
      UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
    } catch (Exception ex) {
      System.out.println("Error setting look-and-feel:\n" + ex);
      System.exit(1);
    }

    initComponents();

    /* Create the tabs. */
    tabRunTest = new RunTestJPanel();
    jTabbedPane1.add(tabRunTest);
//    jTabbedPane1.add(DatabaseJPanel.getReference());
//    jTabbedPane1.add(new ReportJPanel());

    /* Set the tab titles. */
    for (int i = 0; i < jTabbedPane1.getTabCount(); ++i) {
      jTabbedPane1.setTitleAt(i, AppStrings.TabsNames[i]);
    }

    try {
      /* Add the components that should be disabled when working offline. */
      DBConnectionListener.addComponent(disconnectMenuItem);
    } catch (SQLException ex) {
      ErrorDialog.run(AppStrings.createExceptionMessage(ex));
      ex.printStackTrace();
    }

    /* Add this listener to run some code before exit. */
    this.addWindowListener(new WindowAdapter() {

      @Override
      public void windowClosing(WindowEvent evt) {
        close();
      }
    });
  }

  /**
   * Show main application graphical interface.
   */
  public static void run() {
    reference.setVisible(true);
  }

  /**
   * Show a message on the status bar. This method is used to tell the user
   * that some action was successfully performed.
   * 
   * @param text message to display.
   */
  public static void setOKLabel(String text) {
    reference.lbStatus.setText(text);
    reference.lbStatus.setIcon(new javax.swing.ImageIcon(
            reference.getClass().getResource("/ws/performancetest/app/gui/imgs/verified-20.png")));
  }

  /**
   * Get object reference.
   *
   * @return {@code Application} object reference.
   */
  public static javax.swing.JFrame getReference() {
    return reference;
  }

  /**
   * Create temporary file.
   *
   * <p>
   * This also adds this file to a list of temporary files.
   * On application exit all temporary files will be automatically deleted.
   * </p>
   *
   * @param filename name of the temporary file. It should contains only the name,
   *                 because this method will figure out where is the system
   *                 temporary folder.
   *
   * @return file created.
   */
  public static synchronized File createTempFile(String filename) {
    File tempFile = new File(System.getProperty("java.io.tmpdir") + File.separatorChar + filename);
    reference.tempFileList.add(tempFile);
    return tempFile;
  }

  /**
   * Request to refresh the test list on the Run Test tab.
   */
  public static void refreshTestList() {
    //tabRunTest.setTestList();
  }

  /**
   * Find the Test Suites on the classpath.
   *
   * @return list with the test suites found.
   */
  public static List<TestSuite> getTestSuites() {
    if (testSuiteList == null) {
      ServiceLoader<TestSuite> testSuiteProvider = ServiceLoader.load(ws.performancetest.api.TestSuite.class);
      testSuiteList = new LinkedList<TestSuite>();
      for (TestSuite ts : testSuiteProvider) {
        testSuiteList.add(ts);
      }
    }
    return testSuiteList;
  }

  private static synchronized void removeAllTempFiles() {
    for (File file : reference.tempFileList) {
      file.delete();
    }
  }

  private void close() {
    System.out.println("Bye!");
    removeAllTempFiles();

    System.exit(0);
  }

  public static String getPassword() {
    return password;
  }

  public static void setPassword(String password) {
    Application.password = password;
  }

  public static String getPort() {
    return port;
  }

  public static void setPort(String port) {
    Application.port = port;
  }

  public static String getServer() {
    return server;
  }

  public static void setServer(String server) {
    Application.server = server;
  }

  public static String getUsername() {
    return username;
  }

  public static void setUsername(String username) {
    Application.username = username;
  }

  public static String getDatabase() {
    return database;
  }

  public static void setDatabase(String database) {
    Application.database = database;
  }

  /** This method is called from within the constructor to
   * initialize the form.
   * WARNING: Do NOT modify this code. The content of this method is
   * always regenerated by the Form Editor.
   */
  @SuppressWarnings("unchecked")
  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
  private void initComponents() {

    jTabbedPane1 = new javax.swing.JTabbedPane();
    jPanel1 = new javax.swing.JPanel();
    lbStatus = new javax.swing.JLabel();
    menuBar = new javax.swing.JMenuBar();
    fileMenu = new javax.swing.JMenu();
    connectMenuItem = new javax.swing.JMenuItem();
    disconnectMenuItem = new javax.swing.JMenuItem();
    jSeparator2 = new javax.swing.JPopupMenu.Separator();
    exitMenuItem = new javax.swing.JMenuItem();
    helpMenu = new javax.swing.JMenu();
    userManual = new javax.swing.JMenuItem();

    setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
    setTitle(AppStrings.AppName);
    setResizable(false);

    lbStatus.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
      public void propertyChange(java.beans.PropertyChangeEvent evt) {
        lbStatusPropertyChange(evt);
      }
    });

    javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
    jPanel1.setLayout(jPanel1Layout);
    jPanel1Layout.setHorizontalGroup(
      jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
      .addGap(0, 640, Short.MAX_VALUE)
      .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addComponent(lbStatus, javax.swing.GroupLayout.DEFAULT_SIZE, 640, Short.MAX_VALUE))
    );
    jPanel1Layout.setVerticalGroup(
      jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
      .addGap(0, 22, Short.MAX_VALUE)
      .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addComponent(lbStatus, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 22, Short.MAX_VALUE))
    );

    fileMenu.setText("File");
    fileMenu.setPreferredSize(new java.awt.Dimension(50, 21));

    connectMenuItem.setText(AppStrings.menuConnectTo);
    connectMenuItem.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        connectToMenuActionPerformed(evt);
      }
    });
    fileMenu.add(connectMenuItem);

    disconnectMenuItem.setText(AppStrings.menuDisconnect);
    disconnectMenuItem.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        disconnectMenuActionPerformed(evt);
      }
    });
    fileMenu.add(disconnectMenuItem);
    fileMenu.add(jSeparator2);

    exitMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_Q, java.awt.event.InputEvent.CTRL_MASK));
    exitMenuItem.setText("Exit");
    exitMenuItem.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        exitMenuItemActionPerformed(evt);
      }
    });
    fileMenu.add(exitMenuItem);

    menuBar.add(fileMenu);

    helpMenu.setText("Help");

    userManual.setText("User Manual");
    userManual.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        userManualActionPerformed(evt);
      }
    });
    helpMenu.add(userManual);

    menuBar.add(helpMenu);

    setJMenuBar(menuBar);

    javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
    getContentPane().setLayout(layout);
    layout.setHorizontalGroup(
      layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
      .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
      .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addComponent(jTabbedPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 640, Short.MAX_VALUE))
    );
    layout.setVerticalGroup(
      layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
      .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
        .addContainerGap(309, Short.MAX_VALUE)
        .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
      .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addGroup(layout.createSequentialGroup()
          .addComponent(jTabbedPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 308, javax.swing.GroupLayout.PREFERRED_SIZE)
          .addContainerGap(23, Short.MAX_VALUE)))
    );

    pack();
  }// </editor-fold>//GEN-END:initComponents

    private void exitMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_exitMenuItemActionPerformed
      close();
    }//GEN-LAST:event_exitMenuItemActionPerformed

    private void connectToMenuActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_connectToMenuActionPerformed
      DBConnectFrame.run();
    }//GEN-LAST:event_connectToMenuActionPerformed

    private void disconnectMenuActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_disconnectMenuActionPerformed
      try {
        DBConnection.closeDBCon();
      } catch (SQLException ex) {
        ErrorDialog.run(AppStrings.createExceptionMessage(ex));
        ex.printStackTrace();
      }
    }//GEN-LAST:event_disconnectMenuActionPerformed
  private Thread statusCleaner = new Thread();
    private void lbStatusPropertyChange(java.beans.PropertyChangeEvent evt) {//GEN-FIRST:event_lbStatusPropertyChange
      if (!lbStatus.getText().isEmpty()) {
        /* if the text changed, this means that it should  
         * be erased after a few seconds.
         */
        statusCleaner.interrupt();
        statusCleaner = new Thread(new Runnable() {

          public void run() {
            try {
              Thread.sleep(cleanStatusTimeOut);
              lbStatus.setText("");
              lbStatus.setIcon(null);
            } catch (InterruptedException ex) {
              // It's ok be interrupted.
            }
          }
        });
        statusCleaner.start();
      }
    }//GEN-LAST:event_lbStatusPropertyChange

    private void userManualActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_userManualActionPerformed
      Desktop desktop = Desktop.getDesktop();
      try {
        desktop.open(new File("manual" + File.separator + "manual.pdf"));
      } catch (IOException ex) {
        Logger.getLogger(Application.class.getName()).log(Level.SEVERE, null, ex);
      }
    }//GEN-LAST:event_userManualActionPerformed
  // Variables declaration - do not modify//GEN-BEGIN:variables
  private javax.swing.JMenuItem connectMenuItem;
  private javax.swing.JMenuItem disconnectMenuItem;
  private javax.swing.JMenuItem exitMenuItem;
  private javax.swing.JMenu fileMenu;
  private javax.swing.JMenu helpMenu;
  private javax.swing.JPanel jPanel1;
  private javax.swing.JPopupMenu.Separator jSeparator2;
  private javax.swing.JTabbedPane jTabbedPane1;
  private javax.swing.JLabel lbStatus;
  private javax.swing.JMenuBar menuBar;
  private javax.swing.JMenuItem userManual;
  // End of variables declaration//GEN-END:variables
}
